home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / Make / source / glob / glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  24.1 KB  |  1,031 lines

  1. /* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
  2.  
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public License as
  5.    published by the Free Software Foundation; either version 2 of the
  6.    License, or (at your option) any later version.
  7.  
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.  
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; see the file COPYING.LIB.  If not,
  15.    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16.    Boston, MA 02111-1307, USA.  */
  17.  
  18. /* AIX requires this to be the first thing in the file.  */
  19. #if defined (_AIX) && !defined (__GNUC__)
  20.  #pragma alloca
  21. #endif
  22.  
  23. #ifdef    HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26.  
  27. /* Enable GNU extensions in glob.h.  */
  28. #ifndef _GNU_SOURCE
  29. #define    _GNU_SOURCE    1
  30. #endif
  31.  
  32. #include <errno.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35.  
  36. /* Outcomment the following line for production quality code.  */
  37. /* #define NDEBUG 1 */
  38. #include <assert.h>
  39.  
  40. #include <stdio.h>        /* Needed on stupid SunOS for assert.  */
  41.  
  42.  
  43. /* Comment out all this code if we are using the GNU C Library, and are not
  44.    actually compiling the library itself.  This code is part of the GNU C
  45.    Library, but also included in many other GNU distributions.  Compiling
  46.    and linking in this code is a waste when using the GNU C library
  47.    (especially if it is a shared library).  Rather than having every GNU
  48.    program understand `configure --with-gnu-libc' and omit the object files,
  49.    it is simpler to just do this in the source for each such file.  */
  50.  
  51. #define GLOB_INTERFACE_VERSION 1
  52. #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
  53. #include <gnu-versions.h>
  54. #if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
  55. #define ELIDE_CODE
  56. #endif
  57. #endif
  58.  
  59. #ifndef ELIDE_CODE
  60.  
  61. #if defined(STDC_HEADERS) || defined(__GNU_LIBRARY__)
  62. #include <stddef.h>
  63. #endif
  64.  
  65. #if defined HAVE_UNISTD_H || defined _LIBC
  66. #include <unistd.h>
  67. #ifndef POSIX
  68. #ifdef    _POSIX_VERSION
  69. #define    POSIX
  70. #endif
  71. #endif
  72. #endif
  73.  
  74. #if !defined (_AMIGA) && !defined (VMS) && !defined(WINDOWS32)
  75. #include <pwd.h>
  76. #endif
  77.  
  78. #if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
  79. extern int errno;
  80. #endif
  81. #ifndef __set_errno
  82. #define __set_errno(val) errno = (val)
  83. #endif
  84.  
  85. #ifndef    NULL
  86. #define    NULL    0
  87. #endif
  88.  
  89.  
  90. #if defined (HAVE_DIRENT_H) || defined (__GNU_LIBRARY__)
  91. # include <dirent.h>
  92. # define NAMLEN(dirent) strlen((dirent)->d_name)
  93. #else
  94. # define dirent direct
  95. # define NAMLEN(dirent) (dirent)->d_namlen
  96. # ifdef HAVE_SYS_NDIR_H
  97. #  include <sys/ndir.h>
  98. # endif
  99. # ifdef HAVE_SYS_DIR_H
  100. #  include <sys/dir.h>
  101. # endif
  102. # ifdef HAVE_NDIR_H
  103. #  include <ndir.h>
  104. # endif
  105. # ifdef HAVE_VMSDIR_H
  106. #  include "vmsdir.h"
  107. # endif /* HAVE_VMSDIR_H */
  108. #endif
  109.  
  110.  
  111. /* In GNU systems, <dirent.h> defines this macro for us.  */
  112. #ifdef _D_NAMLEN
  113. #undef NAMLEN
  114. #define NAMLEN(d) _D_NAMLEN(d)
  115. #endif
  116.  
  117.  
  118. #if (defined (POSIX) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
  119. /* Posix does not require that the d_ino field be present, and some
  120.    systems do not provide it. */
  121. #define REAL_DIR_ENTRY(dp) 1
  122. #else
  123. #define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
  124. #endif /* POSIX */
  125.  
  126. #if    (defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
  127. #include <stdlib.h>
  128. #include <string.h>
  129. #define    ANSI_STRING
  130. #else    /* No standard headers.  */
  131.  
  132. extern char *getenv ();
  133.  
  134. #ifdef HAVE_STRING_H
  135. #include <string.h>
  136. #define    ANSI_STRING
  137. #else
  138. #include <strings.h>
  139. #endif
  140. #ifdef    HAVE_MEMORY_H
  141. #include <memory.h>
  142. #endif
  143.  
  144. extern char *malloc (), *realloc ();
  145. extern void free ();
  146.  
  147. extern void qsort ();
  148. extern void abort (), exit ();
  149.  
  150. #endif    /* Standard headers.  */
  151.  
  152. #ifndef    ANSI_STRING
  153.  
  154. #ifndef    bzero
  155. extern void bzero ();
  156. #endif
  157. #ifndef    bcopy
  158. extern void bcopy ();
  159. #endif
  160.  
  161. #define    memcpy(d, s, n)    bcopy ((s), (d), (n))
  162. #define    strrchr    rindex
  163. /* memset is only used for zero here, but let's be paranoid.  */
  164. #define    memset(s, better_be_zero, n) \
  165.   ((void) ((better_be_zero) == 0 ? (bzero((s), (n)), 0) : (abort(), 0)))
  166. #endif    /* Not ANSI_STRING.  */
  167.  
  168. #if !defined HAVE_STRCOLL && !defined _LIBC
  169. #define    strcoll    strcmp
  170. #endif
  171.  
  172.  
  173. #ifndef    __GNU_LIBRARY__
  174. #ifdef    __GNUC__
  175. __inline
  176. #endif
  177. #ifndef __SASC
  178. #ifdef WINDOWS32
  179. static void *
  180. #else
  181. static char *
  182. #endif
  183. my_realloc (p, n)
  184.      char *p;
  185.      unsigned int n;
  186. {
  187.   /* These casts are the for sake of the broken Ultrix compiler,
  188.      which warns of illegal pointer combinations otherwise.  */
  189.   if (p == NULL)
  190.     return (char *) malloc (n);
  191.   return (char *) realloc (p, n);
  192. }
  193. #define    realloc    my_realloc
  194. #endif /* __SASC */
  195. #endif /* __GNU_LIBRARY__ */
  196.  
  197.  
  198. #if    !defined(__alloca) && !defined(__GNU_LIBRARY__)
  199.  
  200. #ifdef    __GNUC__
  201. #undef    alloca
  202. #define    alloca(n)    __builtin_alloca (n)
  203. #else    /* Not GCC.  */
  204. #ifdef HAVE_ALLOCA_H
  205. #include <alloca.h>
  206. #else    /* Not HAVE_ALLOCA_H.  */
  207. #ifndef    _AIX
  208. #ifdef WINDOWS32
  209. #include <malloc.h>
  210. #else
  211. extern char *alloca ();
  212. #endif /* WINDOWS32 */
  213. #endif    /* Not _AIX.  */
  214. #endif    /* sparc or HAVE_ALLOCA_H.  */
  215. #endif    /* GCC.  */
  216.  
  217. #define    __alloca    alloca
  218.  
  219. #endif
  220.  
  221. #ifndef __GNU_LIBRARY__
  222. #define __stat stat
  223. #ifdef STAT_MACROS_BROKEN
  224. #undef S_ISDIR
  225. #endif
  226. #ifndef S_ISDIR
  227. #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
  228. #endif
  229. #endif
  230.  
  231. #if !(defined (STDC_HEADERS) || defined (__GNU_LIBRARY__))
  232. #undef    size_t
  233. #define    size_t    unsigned int
  234. #endif
  235.  
  236. /* Some system header files erroneously define these.
  237.    We want our own definitions from <fnmatch.h> to take precedence.  */
  238. #undef    FNM_PATHNAME
  239. #undef    FNM_NOESCAPE
  240. #undef    FNM_PERIOD
  241. #include <fnmatch.h>
  242.  
  243. /* Some system header files erroneously define these.
  244.    We want our own definitions from <glob.h> to take precedence.  */
  245. #undef    GLOB_ERR
  246. #undef    GLOB_MARK
  247. #undef    GLOB_NOSORT
  248. #undef    GLOB_DOOFFS
  249. #undef    GLOB_NOCHECK
  250. #undef    GLOB_APPEND
  251. #undef    GLOB_NOESCAPE
  252. #undef    GLOB_PERIOD
  253. #include <glob.h>
  254.  
  255. static int glob_in_dir __P ((const char *pattern, const char *directory,
  256.                  int flags,
  257.                  int (*errfunc) __P ((const char *, int)),
  258.                  glob_t *pglob));
  259. static int prefix_array __P ((const char *prefix, char **array, size_t n));
  260. static int collated_compare __P ((const __ptr_t, const __ptr_t));
  261.  
  262.  
  263. /* Find the end of the sub-pattern in a brace expression.  We define
  264.    this as an inline function if the compiler permits.  */
  265. static
  266. #if __GNUC__ - 0 >= 2
  267. inline
  268. #endif
  269. const char *
  270. next_brace_sub (begin)
  271.      const char *begin;
  272. {
  273.   unsigned int depth = 0;
  274.   const char *cp = begin;
  275.  
  276.   while (1)
  277.     {
  278.       if (depth == 0)
  279.     {
  280.       if (*cp != ',' && *cp != '}' && *cp != '\0')
  281.         {
  282.           if (*cp == '{')
  283.         ++depth;
  284.           ++cp;
  285.           continue;
  286.         }
  287.     }
  288.       else
  289.     {
  290.       while (*cp != '\0' && (*cp != '}' || depth > 0))
  291.         {
  292.           if (*cp == '}')
  293.         --depth;
  294.           ++cp;
  295.         }
  296.       if (*cp == '\0')
  297.         /* An incorrectly terminated brace expression.  */
  298.         return NULL;
  299.  
  300.       continue;
  301.     }
  302.       break;
  303.     }
  304.  
  305.   return cp;
  306. }
  307.  
  308. /* Do glob searching for PATTERN, placing results in PGLOB.
  309.    The bits defined above may be set in FLAGS.
  310.    If a directory cannot be opened or read and ERRFUNC is not nil,
  311.    it is called with the pathname that caused the error, and the
  312.    `errno' value from the failing call; if it returns non-zero
  313.    `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored.
  314.    If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned.
  315.    Otherwise, `glob' returns zero.  */
  316. int
  317. glob (pattern, flags, errfunc, pglob)
  318.      const char *pattern;
  319.      int flags;
  320.      int (*errfunc) __P ((const char *, int));
  321.      glob_t *pglob;
  322. {
  323.   const char *filename;
  324.   char *dirname;
  325.   size_t dirlen;
  326.   int status;
  327.   int oldcount;
  328.  
  329.   if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0)
  330.     {
  331.       __set_errno (EINVAL);
  332.       return -1;
  333.     }
  334.  
  335.   if (flags & GLOB_BRACE)
  336.     {
  337.       const char *begin = strchr (pattern, '{');
  338.       if (begin != NULL)
  339.     {
  340.       /* Allocate working buffer large enough for our work.  Note that
  341.         we have at least an opening and closing brace.  */
  342.       int firstc;
  343.       char *alt_start;
  344.       const char *p;
  345.       const char *next;
  346.       const char *rest;
  347.       size_t rest_len;
  348. #ifdef __GNUC__
  349.       char onealt[strlen (pattern) - 1];
  350. #else
  351.       char *onealt = (char *) malloc (strlen (pattern) - 1);
  352.       if (onealt == NULL)
  353.         {
  354.           if (!(flags & GLOB_APPEND))
  355.         globfree (pglob);
  356.           return GLOB_NOSPACE;
  357.         }
  358. #endif
  359.  
  360.       /* We know the prefix for all sub-patterns.  */
  361.       memcpy (onealt, pattern, begin - pattern);
  362.       alt_start = &onealt[begin - pattern];
  363.  
  364.       /* Find the first sub-pattern and at the same time find the
  365.          rest after the closing brace.  */
  366.       next = next_brace_sub (begin + 1);
  367.       if (next == NULL)
  368.         {
  369.           /* It is an illegal expression.  */
  370. #ifndef __GNUC__
  371.           free (onealt);
  372. #endif
  373.           return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
  374.         }
  375.  
  376.       /* Now find the end of the whole brace expression.  */
  377.       rest = next;
  378.       while (*rest != '}')
  379.         {
  380.           rest = next_brace_sub (rest + 1);
  381.           if (rest == NULL)
  382.         {
  383.           /* It is an illegal expression.  */
  384. #ifndef __GNUC__
  385.           free (onealt);
  386. #endif
  387.           return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob);
  388.         }
  389.         }
  390.       /* Please note that we now can be sure the brace expression
  391.          is well-formed.  */
  392.       rest_len = strlen (++rest) + 1;
  393.  
  394.       /* We have a brace expression.  BEGIN points to the opening {,
  395.          NEXT points past the terminator of the first element, and END
  396.          points past the final }.  We will accumulate result names from
  397.          recursive runs for each brace alternative in the buffer using
  398.          GLOB_APPEND.  */
  399.  
  400.       if (!(flags & GLOB_APPEND))
  401.         {
  402.           /* This call is to set a new vector, so clear out the
  403.          vector so we can append to it.  */
  404.           pglob->gl_pathc = 0;
  405.           pglob->gl_pathv = NULL;
  406.         }
  407.       firstc = pglob->gl_pathc;
  408.  
  409.       p = begin + 1;
  410.       while (1)
  411.         {
  412.           int result;
  413.  
  414.           /* Construct the new glob expression.  */
  415.           memcpy (alt_start, p, next - p);
  416.           memcpy (&alt_start[next - p], rest, rest_len);
  417.  
  418.           result = glob (onealt,
  419.                  ((flags & ~(GLOB_NOCHECK|GLOB_NOMAGIC))
  420.                   | GLOB_APPEND), errfunc, pglob);
  421.  
  422.           /* If we got an error, return it.  */
  423.           if (result && result != GLOB_NOMATCH)
  424.         {
  425. #ifndef __GNUC__
  426.           free (onealt);
  427. #endif
  428.           if (!(flags & GLOB_APPEND))
  429.             globfree (pglob);
  430.           return result;
  431.         }
  432.  
  433.           if (*next == '}')
  434.         /* We saw the last entry.  */
  435.         break;
  436.  
  437.           p = next + 1;
  438.           next = next_brace_sub (p);
  439.           assert (next != NULL);
  440.         }
  441.  
  442. #ifndef __GNUC__
  443.       free (onealt);
  444. #endif
  445.  
  446.       if (pglob->gl_pathc != firstc)
  447.         /* We found some entries.  */
  448.         return 0;
  449.       else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC)))
  450.         return GLOB_NOMATCH;
  451.     }
  452.     }
  453.  
  454.   /* Find the filename.  */
  455.   filename = strrchr (pattern, '/');
  456.   if (filename == NULL)
  457.     {
  458.       filename = pattern;
  459. #ifdef _AMIGA
  460.       dirname = (char *) "";
  461. #else
  462.       dirname = (char *) ".";
  463. #endif
  464.       dirlen = 0;
  465.     }
  466.   else if (filename == pattern)
  467.     {
  468.       /* "/pattern".  */
  469.       dirname = (char *) "/";
  470.       dirlen = 1;
  471.       ++filename;
  472.     }
  473.   else
  474.     {
  475.       dirlen = filename - pattern;
  476.       dirname = (char *) __alloca (dirlen + 1);
  477.       memcpy (dirname, pattern, dirlen);
  478.       dirname[dirlen] = '\0';
  479.       ++filename;
  480.     }
  481.  
  482.   if (filename[0] == '\0' && dirlen > 1)
  483.     /* "pattern/".  Expand "pattern", appending slashes.  */
  484.     {
  485.       int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob);
  486.       if (val == 0)
  487.     pglob->gl_flags = (pglob->gl_flags & ~GLOB_MARK) | (flags & GLOB_MARK);
  488.       return val;
  489.     }
  490.  
  491.   if (!(flags & GLOB_APPEND))
  492.     {
  493.       pglob->gl_pathc = 0;
  494.       pglob->gl_pathv = NULL;
  495.     }
  496.  
  497.   oldcount = pglob->gl_pathc;
  498.  
  499. #ifndef VMS
  500.   if ((flags & GLOB_TILDE) && dirname[0] == '~')
  501.     {
  502.       if (dirname[1] == '\0' || dirname[1] == '/')
  503.     {
  504.       /* Look up home directory.  */
  505.       char *home_dir = getenv ("HOME");
  506. #ifdef _AMIGA
  507.       if (home_dir == NULL || home_dir[0] == '\0')
  508.         home_dir = "SYS:";
  509. #else
  510. #ifdef WINDOWS32
  511.       if (home_dir == NULL || home_dir[0] == '\0')
  512.             home_dir = "c:/users/default"; /* poor default */
  513. #else
  514.       if (home_dir == NULL || home_dir[0] == '\0')
  515.         {
  516.           int success;
  517. #if defined HAVE_GETLOGIN_R || defined _LIBC
  518.           extern int getlogin_r __P ((char *, size_t));
  519.           size_t buflen = sysconf (_SC_LOGIN_NAME_MAX) + 1;
  520.           char *name;
  521.  
  522.           if (buflen == 0)
  523.         /* `sysconf' does not support _SC_LOGIN_NAME_MAX.  Try
  524.            a moderate value.  */
  525.         buflen = 16;
  526.           name = (char *) __alloca (buflen);
  527.  
  528.           success = getlogin_r (name, buflen) >= 0;
  529. #else
  530.           extern char *getlogin __P ((void));
  531.           char *name;
  532.  
  533.           success = (name = getlogin ()) != NULL;
  534. #endif
  535.           if (success)
  536.         {
  537. #if defined HAVE_GETPWNAM_R || defined _LIBC
  538.           size_t pwbuflen = sysconf (_SC_GETPW_R_SIZE_MAX);
  539.           char *pwtmpbuf;
  540.           struct passwd pwbuf, *p;
  541.  
  542.           pwtmpbuf = (char *) __alloca (pwbuflen);
  543.  
  544.           success = (__getpwnam_r (name, &pwbuf, pwtmpbuf,
  545.                        pwbuflen, &p) >= 0);
  546. #else
  547.           struct passwd *p = getpwnam (name);
  548.           success = p != NULL;
  549. #endif
  550.           if (success)
  551.             home_dir = p->pw_dir;
  552.         }
  553.         }
  554.       if (home_dir == NULL || home_dir[0] == '\0')
  555.         home_dir = (char *) "~"; /* No luck.  */
  556. #endif /* WINDOWS32 */
  557. #endif
  558.       /* Now construct the full directory.  */
  559.       if (dirname[1] == '\0')
  560.         dirname = home_dir;
  561.       else
  562.         {
  563.           char *newp;
  564.           size_t home_len = strlen (home_dir);
  565.           newp = (char *) __alloca (home_len + dirlen);
  566.           memcpy (newp, home_dir, home_len);
  567.           memcpy (&newp[home_len], &dirname[1], dirlen);
  568.           dirname = newp;
  569.         }
  570.     }
  571. #if !defined _AMIGA && !defined WINDOWS32
  572.       else
  573.     {
  574.       char *end_name = strchr (dirname, '/');
  575.       char *user_name;
  576.       char *home_dir;
  577.  
  578.       if (end_name == NULL)
  579.         user_name = dirname + 1;
  580.       else
  581.         {
  582.           user_name = (char *) __alloca (end_name - dirname);
  583.           memcpy (user_name, dirname + 1, end_name - dirname);
  584.           user_name[end_name - dirname - 1] = '\0';
  585.         }
  586.  
  587.       /* Look up specific user's home directory.  */
  588.       {
  589. #if defined HAVE_GETPWNAM_R || defined _LIBC
  590.         size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
  591.         char *pwtmpbuf = (char *) __alloca (buflen);
  592.         struct passwd pwbuf, *p;
  593.         if (__getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) >= 0)
  594.           home_dir = p->pw_dir;
  595.         else
  596.           home_dir = NULL;
  597. #else
  598.         struct passwd *p = getpwnam (user_name);
  599.         if (p != NULL)
  600.           home_dir = p->pw_dir;
  601.         else
  602.           home_dir = NULL;
  603. #endif
  604.       }
  605.       /* If we found a home directory use this.  */
  606.       if (home_dir != NULL)
  607.         {
  608.           char *newp;
  609.           size_t home_len = strlen (home_dir);
  610.           size_t rest_len = end_name == NULL ? 0 : strlen (end_name);
  611.           newp = (char *) __alloca (home_len + rest_len + 1);
  612.           memcpy (newp, home_dir, home_len);
  613.           memcpy (&newp[home_len], end_name, rest_len);
  614.           newp[home_len + rest_len] = '\0';
  615.           dirname = newp;
  616.         }
  617.     }
  618. #endif    /* Not Amiga && not WINDOWS32.  */
  619.     }
  620. #endif    /* Not VMS.  */
  621.  
  622.   if (__glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE)))
  623.     {
  624.       /* The directory name contains metacharacters, so we
  625.      have to glob for the directory, and then glob for
  626.      the pattern in each directory found.  */
  627.       glob_t dirs;
  628.       register int i;
  629.  
  630.       status = glob (dirname,
  631.              ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE)) |
  632.               GLOB_NOSORT),
  633.              errfunc, &dirs);
  634.       if (status != 0)
  635.     return status;
  636.  
  637.       /* We have successfully globbed the preceding directory name.
  638.      For each name we found, call glob_in_dir on it and FILENAME,
  639.      appending the results to PGLOB.  */
  640.       for (i = 0; i < dirs.gl_pathc; ++i)
  641.     {
  642.       int oldcount;
  643.  
  644. #ifdef    SHELL
  645.       {
  646.         /* Make globbing interruptible in the bash shell. */
  647.         extern int interrupt_state;
  648.  
  649.         if (interrupt_state)
  650.           {
  651.         globfree (&dirs);
  652.         globfree (&files);
  653.         return GLOB_ABORTED;
  654.           }
  655.       }
  656. #endif /* SHELL.  */
  657.  
  658.       oldcount = pglob->gl_pathc;
  659.       status = glob_in_dir (filename, dirs.gl_pathv[i],
  660.                 (flags | GLOB_APPEND) & ~GLOB_NOCHECK,
  661.                 errfunc, pglob);
  662.       if (status == GLOB_NOMATCH)
  663.         /* No matches in this directory.  Try the next.  */
  664.         continue;
  665.  
  666.       if (status != 0)
  667.         {
  668.           globfree (&dirs);
  669.           globfree (pglob);
  670.           return status;
  671.         }
  672.  
  673.       /* Stick the directory on the front of each name.  */
  674.       if (prefix_array (dirs.gl_pathv[i],
  675.                 &pglob->gl_pathv[oldcount],
  676.                 pglob->gl_pathc - oldcount))
  677.         {
  678.           globfree (&dirs);
  679.           globfree (pglob);
  680.           return GLOB_NOSPACE;
  681.         }
  682.     }
  683.  
  684.       flags |= GLOB_MAGCHAR;
  685.  
  686.       if (pglob->gl_pathc == oldcount)
  687.     /* No matches.  */
  688.     if (flags & GLOB_NOCHECK)
  689.       {
  690.         size_t len = strlen (pattern) + 1;
  691.         char *patcopy = (char *) malloc (len);
  692.         if (patcopy == NULL)
  693.           return GLOB_NOSPACE;
  694.         memcpy (patcopy, pattern, len);
  695.  
  696.         pglob->gl_pathv
  697.           = (char **) realloc (pglob->gl_pathv,
  698.                    (pglob->gl_pathc +
  699.                     ((flags & GLOB_DOOFFS) ?
  700.                      pglob->gl_offs : 0) +
  701.                     1 + 1) *
  702.                    sizeof (char *));
  703.         if (pglob->gl_pathv == NULL)
  704.           {
  705.         free (patcopy);
  706.         return GLOB_NOSPACE;
  707.           }
  708.  
  709.         if (flags & GLOB_DOOFFS)
  710.           while (pglob->gl_pathc < pglob->gl_offs)
  711.         pglob->gl_pathv[pglob->gl_pathc++] = NULL;
  712.  
  713.         pglob->gl_pathv[pglob->gl_pathc++] = patcopy;
  714.         pglob->gl_pathv[pglob->gl_pathc] = NULL;
  715.         pglob->gl_flags = flags;
  716.       }
  717.     else
  718.       return GLOB_NOMATCH;
  719.     }
  720.   else
  721.     {
  722.       status = glob_in_dir (filename, dirname, flags, errfunc, pglob);
  723.       if (status != 0)
  724.     return status;
  725.  
  726.       if (dirlen > 0)
  727.     {
  728.       /* Stick the directory on the front of each name.  */
  729.       if (prefix_array (dirname,
  730.                 &pglob->gl_pathv[oldcount],
  731.                 pglob->gl_pathc - oldcount))
  732.         {
  733.           globfree (pglob);
  734.           return GLOB_NOSPACE;
  735.         }
  736.     }
  737.     }
  738.  
  739.   if (flags & GLOB_MARK)
  740.     {
  741.       /* Append slashes to directory names.  */
  742.       int i;
  743.       struct stat st;
  744.       for (i = oldcount; i < pglob->gl_pathc; ++i)
  745.     if (((flags & GLOB_ALTDIRFUNC) ?
  746.          (*pglob->gl_stat) (pglob->gl_pathv[i], &st) :
  747.          __stat (pglob->gl_pathv[i], &st)) == 0 &&
  748.         S_ISDIR (st.st_mode))
  749.       {
  750.          size_t len = strlen (pglob->gl_pathv[i]) + 2;
  751.         char *new = realloc (pglob->gl_pathv[i], len);
  752.          if (new == NULL)
  753.           {
  754.         globfree (pglob);
  755.         return GLOB_NOSPACE;
  756.           }
  757.         strcpy (&new[len - 2], "/");
  758.         pglob->gl_pathv[i] = new;
  759.       }
  760.     }
  761.  
  762.   if (!(flags & GLOB_NOSORT))
  763.     /* Sort the vector.  */
  764.     qsort ((__ptr_t) &pglob->gl_pathv[oldcount],
  765.        pglob->gl_pathc - oldcount,
  766.        sizeof (char *), collated_compare);
  767.  
  768.   return 0;
  769. }
  770.  
  771.  
  772. /* Free storage allocated in PGLOB by a previous `glob' call.  */
  773. void
  774. globfree (pglob)
  775.      register glob_t *pglob;
  776. {
  777.   if (pglob->gl_pathv != NULL)
  778.     {
  779.       register int i;
  780.       for (i = 0; i < pglob->gl_pathc; ++i)
  781.     if (pglob->gl_pathv[i] != NULL)
  782.       free ((__ptr_t) pglob->gl_pathv[i]);
  783.       free ((__ptr_t) pglob->gl_pathv);
  784.     }
  785. }
  786.  
  787.  
  788. /* Do a collated comparison of A and B.  */
  789. static int
  790. collated_compare (a, b)
  791.      const __ptr_t a;
  792.      const __ptr_t b;
  793. {
  794.   const char *const s1 = *(const char *const * const) a;
  795.   const char *const s2 = *(const char *const * const) b;
  796.  
  797.   if (s1 == s2)
  798.     return 0;
  799.   if (s1 == NULL)
  800.     return 1;
  801.   if (s2 == NULL)
  802.     return -1;
  803.   return strcoll (s1, s2);
  804. }
  805.  
  806.  
  807. /* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's
  808.    elements in place.  Return nonzero if out of memory, zero if successful.
  809.    A slash is inserted between DIRNAME and each elt of ARRAY,
  810.    unless DIRNAME is just "/".  Each old element of ARRAY is freed.  */
  811. static int
  812. prefix_array (dirname, array, n)
  813.      const char *dirname;
  814.      char **array;
  815.      size_t n;
  816. {
  817.   register size_t i;
  818.   size_t dirlen = strlen (dirname);
  819.  
  820.   if (dirlen == 1 && dirname[0] == '/')
  821.     /* DIRNAME is just "/", so normal prepending would get us "//foo".
  822.        We want "/foo" instead, so don't prepend any chars from DIRNAME.  */
  823.     dirlen = 0;
  824.  
  825.   for (i = 0; i < n; ++i)
  826.     {
  827.       size_t eltlen = strlen (array[i]) + 1;
  828.       char *new = (char *) malloc (dirlen + 1 + eltlen);
  829.       if (new == NULL)
  830.     {
  831.       while (i > 0)
  832.         free ((__ptr_t) array[--i]);
  833.       return 1;
  834.     }
  835.  
  836.       memcpy (new, dirname, dirlen);
  837.       new[dirlen] = '/';
  838.       memcpy (&new[dirlen + 1], array[i], eltlen);
  839.       free ((__ptr_t) array[i]);
  840.       array[i] = new;
  841.     }
  842.  
  843.   return 0;
  844. }
  845.  
  846.  
  847. /* Return nonzero if PATTERN contains any metacharacters.
  848.    Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
  849. int
  850. __glob_pattern_p (pattern, quote)
  851.      const char *pattern;
  852.      int quote;
  853. {
  854.   register const char *p;
  855.   int open = 0;
  856.  
  857.   for (p = pattern; *p != '\0'; ++p)
  858.     switch (*p)
  859.       {
  860.       case '?':
  861.       case '*':
  862.     return 1;
  863.  
  864.       case '\\':
  865.     if (quote && p[1] != '\0')
  866.       ++p;
  867.     break;
  868.  
  869.       case '[':
  870.     open = 1;
  871.     break;
  872.  
  873.       case ']':
  874.     if (open)
  875.       return 1;
  876.     break;
  877.       }
  878.  
  879.   return 0;
  880. }
  881. #ifdef _LIBC
  882. weak_alias (__glob_pattern_p, glob_pattern_p)
  883. #endif
  884.  
  885.  
  886. /* Like `glob', but PATTERN is a final pathname component,
  887.    and matches are searched for in DIRECTORY.
  888.    The GLOB_NOSORT bit in FLAGS is ignored.  No sorting is ever done.
  889.    The GLOB_APPEND flag is assumed to be set (always appends).  */
  890. static int
  891. glob_in_dir (pattern, directory, flags, errfunc, pglob)
  892.      const char *pattern;
  893.      const char *directory;
  894.      int flags;
  895.      int (*errfunc) __P ((const char *, int));
  896.      glob_t *pglob;
  897. {
  898.   __ptr_t stream;
  899.  
  900.   struct globlink
  901.     {
  902.       struct globlink *next;
  903.       char *name;
  904.     };
  905.   struct globlink *names = NULL;
  906.   size_t nfound = 0;
  907.  
  908.   if (!__glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
  909.     {
  910.       stream = NULL;
  911.       flags |= GLOB_NOCHECK;
  912.     }
  913.   else
  914.     {
  915.       flags |= GLOB_MAGCHAR;
  916.  
  917.       stream = ((flags & GLOB_ALTDIRFUNC) ?
  918.         (*pglob->gl_opendir) (directory) :
  919.         (__ptr_t) opendir (directory));
  920.       if (stream == NULL)
  921.     {
  922.       if ((errfunc != NULL && (*errfunc) (directory, errno)) ||
  923.           (flags & GLOB_ERR))
  924.         return GLOB_ABORTED;
  925.     }
  926.       else
  927.     while (1)
  928.       {
  929.         const char *name;
  930.         size_t len;
  931.         struct dirent *d = ((flags & GLOB_ALTDIRFUNC) ?
  932.                 (*pglob->gl_readdir) (stream) :
  933.                 readdir ((DIR *) stream));
  934.         if (d == NULL)
  935.           break;
  936.         if (! REAL_DIR_ENTRY (d))
  937.           continue;
  938.  
  939.         name = d->d_name;
  940.  
  941.         if (fnmatch (pattern, name,
  942.              (!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) |
  943.              ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)
  944. #ifdef _AMIGA
  945.              | FNM_CASEFOLD
  946. #endif
  947.              ) == 0)
  948.           {
  949.         struct globlink *new
  950.           = (struct globlink *) __alloca (sizeof (struct globlink));
  951.         len = NAMLEN (d);
  952.         new->name
  953.           = (char *) malloc (len + 1);
  954.         if (new->name == NULL)
  955.           goto memory_error;
  956.         memcpy ((__ptr_t) new->name, name, len);
  957.         new->name[len] = '\0';
  958.         new->next = names;
  959.         names = new;
  960.         ++nfound;
  961.           }
  962.       }
  963.     }
  964.  
  965.   if (nfound == 0 && (flags & GLOB_NOMAGIC) &&
  966.       ! __glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)))
  967.     flags |= GLOB_NOCHECK;
  968.  
  969.   if (nfound == 0 && (flags & GLOB_NOCHECK))
  970.     {
  971.       size_t len = strlen (pattern);
  972.       nfound = 1;
  973.       names = (struct globlink *) __alloca (sizeof (struct globlink));
  974.       names->next = NULL;
  975.       names->name = (char *) malloc (len + 1);
  976.       if (names->name == NULL)
  977.     goto memory_error;
  978.       memcpy (names->name, pattern, len);
  979.       names->name[len] = '\0';
  980.     }
  981.  
  982.   pglob->gl_pathv
  983.     = (char **) realloc (pglob->gl_pathv,
  984.              (pglob->gl_pathc +
  985.               ((flags & GLOB_DOOFFS) ? pglob->gl_offs : 0) +
  986.               nfound + 1) *
  987.              sizeof (char *));
  988.   if (pglob->gl_pathv == NULL)
  989.     goto memory_error;
  990.  
  991.   if (flags & GLOB_DOOFFS)
  992.     while (pglob->gl_pathc < pglob->gl_offs)
  993.       pglob->gl_pathv[pglob->gl_pathc++] = NULL;
  994.  
  995.   for (; names != NULL; names = names->next)
  996.     pglob->gl_pathv[pglob->gl_pathc++] = names->name;
  997.   pglob->gl_pathv[pglob->gl_pathc] = NULL;
  998.  
  999.   pglob->gl_flags = flags;
  1000.  
  1001.   if (stream != NULL)
  1002.     {
  1003.       int save = errno;
  1004.       if (flags & GLOB_ALTDIRFUNC)
  1005.     (*pglob->gl_closedir) (stream);
  1006.       else
  1007.     closedir ((DIR *) stream);
  1008.       __set_errno (save);
  1009.     }
  1010.   return nfound == 0 ? GLOB_NOMATCH : 0;
  1011.  
  1012.  memory_error:
  1013.   {
  1014.     int save = errno;
  1015.     if (flags & GLOB_ALTDIRFUNC)
  1016.       (*pglob->gl_closedir) (stream);
  1017.     else
  1018.       closedir ((DIR *) stream);
  1019.     __set_errno (save);
  1020.   }
  1021.   while (names != NULL)
  1022.     {
  1023.       if (names->name != NULL)
  1024.     free ((__ptr_t) names->name);
  1025.       names = names->next;
  1026.     }
  1027.   return GLOB_NOSPACE;
  1028. }
  1029.  
  1030. #endif    /* Not ELIDE_CODE.  */
  1031.